﻿using System;
using System.IO.Ports;
using System.Threading;
using Microsoft.Extensions.Logging;

namespace Communication.StreamResource.SerialPortImplementation;

/// <summary>
///     串口通讯
/// </summary>
/// <param name="info"></param>
/// <param name="logger"></param>
public class SerialPortStreamResource(SerialPortConfiguration info, ILogger logger) : IStreamResource
{
    /// <summary>
    ///     初始化串行端口
    /// </summary>
    private readonly SerialPort _port = new(info.PortName, info.BaudRate, info.Parity, info.DataBits, info.StopBits)
        { ReadTimeout = 400, WriteTimeout = 400 };


    public ILogger Logger { get; } = logger;


    public int InfiniteTimeout => SerialPort.InfiniteTimeout;

    public bool Connected => _port.IsOpen;

    public int ReadTimeout
    {
        get => _port.ReadTimeout;
        set => _port.ReadTimeout = value;
    }

    public int WriteTimeout
    {
        get => _port.WriteTimeout;
        set => _port.WriteTimeout = value;
    }

    public void DiscardInBuffer()
    {
        // 记录一条日志
        Logger.LogTrace(nameof(DiscardInBuffer));
        // 丢弃出缓冲区中的数据
        _port.DiscardOutBuffer();
        // 丢弃入缓冲区中的数据
        _port.DiscardInBuffer();
    }

    /// <summary>
    ///     销毁
    /// </summary>
    public void Dispose()
    {
        // 记录日志
        Logger.LogTrace(nameof(Dispose));
        // 释放端口资源
        _port.Dispose();
        // 禁止垃圾回收
        GC.SuppressFinalize(this);
    }

    public int Read(byte[] buffer, int offset, int count)
    {
        // 读取指定长度的数据到缓冲区
        return _port.Read(buffer, offset, count);
    }


    public bool Reset()
    {
        // 记录一条调试信息
        Logger.LogTrace(nameof(Reset));
        // 如果未连接，则打开端口
        if (Connected) return true;
        try
        {
            _port.Open();
        }
        catch (Exception)
        {
            Thread.Sleep(1000);
            throw;
        }

        // 返回是否连接
        return Connected;
    }

    public void Write(byte[] buffer, int offset, int count)
    {
        _port.Write(buffer, offset, count);
    }

    /// <summary>
    ///     转换为字符串
    /// </summary>
    /// <param name="format"></param>
    /// <param name="formatProvider"></param>
    /// <returns></returns>
    public string ToString(string? format, IFormatProvider? formatProvider)
    {
        return info.ToString(format, formatProvider);
    }

    public void Close()
    {
        _port.Close();
    }
}